package service

import (
	"bytes"
	"database/sql"
	"encoding/json"
	"fmt"
	"git.tmuyu.com.cn/beego/models"
	"git.tmuyu.com.cn/beego/util"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/logs"
	"github.com/rs/xid"
	"io/ioutil"
	"net/http"
	"strings"
)

// https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN

func Message(accessToken string, menuJsonBytes []byte) (err error) {
	postReq, err := http.NewRequest("POST",
		strings.Join([]string{"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken}, ""),
		bytes.NewReader(menuJsonBytes))
	if err != nil {
		fmt.Println("发送消息模板请求失败", err)
		logs.Error("发送消息模板请求失败", err)
		return err
	}

	postReq.Header.Set("Content-Type", "application/json; encoding=utf-8")

	client := &http.Client{}
	resp, err := client.Do(postReq)
	if err != nil {
		fmt.Println("client发送消息模板请求失败", err)
		logs.Error("client发送消息模板请求失败", err)
		return err
	} else {
		logs.Info("flash massage")
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if bytes.Contains(body, []byte("errcode")) {
		ater := models.AccessTokenErrorResponse{}
		err = json.Unmarshal(body, &ater)
		if err != nil {
			logs.Error("模板消息回调解析失败的错误信息 %+v\n", ater)
			return err
		}
		if ater.Errcode != 0 {
			logs.Error("模板消息发送失败 Errmsg:", ater.Errmsg)
			logs.Error("模板消息发送失败 errcode:", ater.Errcode)
			return fmt.Errorf("消息发送失败")
		} else {
			logs.Error("模板消息发送的 Errmsg:", ater.Errmsg)
			logs.Error("模板消息发送的 errcode:", ater.Errcode)
		}
	}
	return nil
}
func CreateMessage(t models.CreatMsg) error {
	appId := beego.AppConfig.String("miniprogram_app_id")
	path := beego.AppConfig.String("miniprogram_pagepath")
	if t.Color == "" {
		t.Color = "#173177"
	}
	TemplateId := beego.AppConfig.String("TemplateId")
	menuStr := models.Message{
		ToUser:     t.Openid,
		TemplateId: TemplateId,
		Miniprogram: models.Miniprogram{
			Appid:    appId,
			Pagepath: path,
		},
		Data: models.Data{
			//First: models.Raw{Value: "你收到来自广夏城社区的通知", Color: "#173177"},
			//Keyword1: models.Raw{Value: "请来到xxx", Color: "#173177"},
			//Keyword2: models.Raw{Value: "做xxx", Color: "#173177"},
			//Remark:  models.Raw{Value: "感谢", Color: "#173177"},
			First:    models.Raw{Value: t.First, Color: t.Color},
			Keyword1: models.Raw{Value: t.Keyword1, Color: t.Color},
			Keyword2: models.Raw{Value: t.Keyword2, Color: t.Color},
			Remark:   models.Raw{Value: t.Remark, Color: t.Color},
		},
	}
	menu, err := json.Marshal(menuStr)
	if err != nil {
		logs.Error("menu err:", err)
		return err
	}
	at, _ := GetAndUpdateDBWxAToken()
	//发送模板消息的post请求
	err2 := Message(at, menu)
	if err2 != nil {
		logs.Error("message err:", err)
		return err2
	}
	return nil
}

//700 无此社区
func FindOpenid(data models.SendData) (err error, errcode int) {
	o := util.GetMysqlDb()
	var rows *sql.Rows
	var code models.Code

	switch {
	case data.Code != 0:
		if o.Table("structure").Where(
			"code = ?", data.Code).Select(
			"code").Find(
			&code).RecordNotFound() {
			logs.Error("无此社区：", data.Code)
			return fmt.Errorf("无此社区"), 700
		} else if o.Table("admin").Where("xid = ?").Where("wx_union_id is not null").Where("wx_union_id != \"\"").Select("xid").Find(&code).RecordNotFound() {
			logs.Error("没有绑定微信账号")
			return fmt.Errorf("该账户未绑定，请先使用拥有该社区电子卡的微信小程序绑定后台账号"), 700
		} else {
			strcode := fmt.Sprintf("%d%s", data.Code, "%")
			rows, err = o.Raw("select w.openid from user u right join passcheck p on u.xid = p.apply_id right join user_wx w on w.union_id = u.wx_union_id where p.is_self = 1 and w.openid is not null  and p.status = 2 AND p.code like ?", strcode).Rows()
			logs.Info("rows", rows)
		}
	case data.CadreID != "":
		logs.Info("CadreID")
		if o.Table("admin").Where("xid = ?", data.CadreID).Select("xid").Find(&code).RecordNotFound() {
			logs.Error("查无此人：", data.CadreID)
			return fmt.Errorf("查无此人"), 700
		} else if o.Table("admin").Where("xid = ?").Where("wx_union_id != \"\"").Where("wx_union_id is not null").Select("xid").Find(&code).RecordNotFound() {
			logs.Error("没有绑定微信账号")
			return fmt.Errorf("该账户未绑定，请先使用拥有该社区电子卡的微信小程序绑定后台账号"), 700
		} else {
			rows, err = o.Raw("select w.openid from user u "+
				"right join passcheck p on u.xid = p.apply_id "+
				"right join user_wx w on w.union_id = u.wx_union_id "+
				"where p.is_self = 1 and p.status = 2 and w.openid is not null"+
				"    AND p.cadre_id = ?", data.CadreID).Rows()
		}
	default:
		logs.Warn("openid too many or not")
		return fmt.Errorf("无权限发送"), 700
	}
	if err != nil {
		logs.Warn("sql err:", err.Error())
		if err == sql.ErrNoRows {
			return fmt.Errorf("无用户需要推送"), 700
		}
		return fmt.Errorf("无法发送%s", err), 400
	}
	if rows == nil {
		logs.Error("无用户需要推送")
		return fmt.Errorf("无用户需要推送"), 700
	}
	bytedata, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("模板消息转json失败", err), 500
	}
	strdata := string(bytedata)
	xid := xid.New().String()
	err = util.SetMessage(xid, strdata)
	if err != nil {
		logs.Error("redis set message error: ", err)
		return fmt.Errorf("service error"), 400
	}

	for rows.Next() {
		var Openid models.Openid
		// ScanRows 扫描一行到 user 模型
		err := o.ScanRows(rows, &Openid)
		if err != nil {
			logs.Error("'server/message'Scan error:", err)
			return err, 500
		}

		util.SetFirstList("openid", fmt.Sprintf("%s:%s", Openid.Openid, xid), -1)
	}
	return nil, 0
}

func FindSelfOpenid(data models.SendData) (err error, errcode int) {
	o := util.GetMysqlDb()
	var openid models.Openid
	var code models.Code

	if o.Table("admin").Where("xid = ?", data.CadreID).Where("wx_union_id != \"\"").Where("wx_union_id is not null").Select("xid").Find(&code).RecordNotFound() {
		logs.Error("没有绑定微信账号")
		return fmt.Errorf("该账户未绑定，请先使用拥有该社区电子卡的微信小程序绑定后台账号"), 700
	}

	err = o.Raw("select w.openid from user_wx w left join admin on admin.wx_union_id = w.union_id where w.openid is not null and w.openid!= \"\" and admin.xid = ?", data.CadreID).Scan(&openid).Error
	if err != nil {
		return fmt.Errorf("无法发送，请先通过微邻里公众号-扫码回家进入小程序"), 700
	}

	bytedata, err := json.Marshal(data)
	if err != nil {
		return fmt.Errorf("模板消息转json失败", err), 500
	}

	strdata := string(bytedata)
	xid := xid.New().String()

	err = util.SetMessage(xid, strdata)
	if err != nil {
		logs.Error("redis set message error: ", err)
		return fmt.Errorf("service error"), 400
	}

	util.SetFirstList("openid", fmt.Sprintf("%s:%s", openid.Openid, xid), -1)

	return nil, 0

}
func GetOpenid(limit int) []models.CreatMsg {
	var CreateMsgs []models.CreatMsg
	for i := 0; i < limit; i++ {
		var CreateMsg models.CreatMsg
		var data = &models.SendData{}
		var openid models.Openid

		id := util.GetList("openid")
		//logs.Info("res:",id)
		res := strings.Split(id, ":")
		if len(res) != 2 {
			//logs.Warn("GetOpenid: invalid open id: ", id)
			continue
		}

		id = res[0]
		da := util.GetMessage(res[1])
		if id == "" || da == "" {
			continue
		}

		openid.Openid = id
		err := json.Unmarshal([]byte(da), &data)
		if err != nil {
			logs.Warn("GetOpenid: invalid message: ", err)
			continue
		}

		CreateMsg.Openid = openid.Openid
		CreateMsg.SendData = *data
		CreateMsgs = append(CreateMsgs, CreateMsg)
	}

	return CreateMsgs
}

func CreateSendmsg(CreatMsg models.CreatMsg) (err error, errCode int) {
	if CreatMsg.Openid == "" {
		logs.Warn("no openid", CreatMsg.Openid)
		return fmt.Errorf("not have openid"), 405
	}
	logs.Info("value:", CreatMsg.Openid)
	err = CreateMessage(CreatMsg)
	if err != nil {
		return err, 500
	}
	return nil, 0
}
